package com.ruoyi.web.controller.system;

import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.common.annotation.Anonymous;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.*;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.file.FileUploadUtils;
import com.ruoyi.common.utils.file.MimeTypeUtils;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.framework.web.service.TokenService;
import com.ruoyi.system.service.*;
import com.ruoyi.web.controller.tool.MD5Util;
import com.ruoyi.web.core.config.RestTemplateUtil;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 用户信息
 *
 * @author ruoyi
 */
@RestController
@RequestMapping("/system/user")
public class SysUserController extends BaseController {
    @Autowired
    private ISysUserService userService;

    @Autowired
    private ISysRoleService roleService;

    @Autowired
    private ISysDeptService deptService;

    @Autowired
    private ISysPostService postService;

    @Autowired
    private IImsYzzcSunBranchService imsYzzcSunBranchService;

    @Autowired
    private SharedData sharedData;

    private static final String FILE_DELIMETER = ",";

    @Autowired
    private TokenService tokenService;

    /**
     * 获取用户列表
     */
    @PreAuthorize("@ss.hasPermi('system:user:list')")
    @GetMapping("/list")
    public TableDataInfo list(SysUser user) {
        startPage();
        List<SysUser> list = userService.selectUserList(user);
        return getDataTable(list);
    }

    /**
     * 商家端授权获取token
     *
     * @return 结果
     */
    @GetMapping("/getGPSToken")
    @Anonymous
    public AjaxResult getGPSToken() throws Exception {
        AjaxResult ajax = AjaxResult.success();
        SysUser loginSysUser = SecurityUtils.getLoginUser().getUser();
        if (loginSysUser != null) {
            SysUser sysUser = userService.selectGpsUser(loginSysUser);
            if (ObjectUtils.isEmpty(sysUser)) {
                return AjaxResult.error("未绑定GPS账号");
            }
            if (StringUtils.isNoneBlank(sysUser.getGpsUserName()) && StringUtils.isNoneBlank(sysUser.getGpsPassword())) {
                ajax.put("userId", sysUser.getUserId());
                ajax.put("userName", sysUser.getGpsUserName());
                ajax.put("shopId", loginSysUser.getShopIds());
                ajax.put("phonenumber", sysUser.getPhonenumber());
                ajax.put("companyCertified", sysUser.getCompanyCertified());
                ajax.put("financeCertified", sysUser.getFinanceCertified());
                ajax.put("companyName", sysUser.getCompanyName());
                ajax.put("deptId", sysUser.getDeptId());

                ImsYzzcSunBranch imsYzzcSunBranch = new ImsYzzcSunBranch();
                if (sysUser.getShopIds() != null && sysUser.getShopIds() != "") {
                    imsYzzcSunBranch = imsYzzcSunBranchService.selectImsYzzcSunBranchById(Long.valueOf(sysUser.getShopIds()));
                }
                if (ObjectUtils.isNotEmpty(imsYzzcSunBranch)) {
                    ajax.put("shopName", imsYzzcSunBranch.getName());
                }
                // 获取gps信息
                JSONObject jsonObject = RestTemplateUtil.getGpsTokenByUser(sysUser.getDomainName(), sysUser.getGpsUserName(), sysUser.getGpsPassword());
                if (jsonObject == null) {
                    return AjaxResult.error("用户名或者密码错误");
                }
                String x_token = jsonObject.getString("x_token");
                if (ObjectUtils.isNotEmpty(x_token)) {
                    ajax.put("x_token", x_token);
                    ajax.put("url",sysUser.getDomainName());
                }
                String member_id = jsonObject.getString("member_id");
                if (ObjectUtils.isNotEmpty(member_id)) {
                    ajax.put("member_id", member_id);
                }
            } else {
                return AjaxResult.error("用户名或者密码错误");
            }
        }
        return ajax;
    }

    @PutMapping("/choseGpsAccount/{id}")
    @Anonymous
    public AjaxResult choseGpsAccount(@PathVariable Long id) {
        LoginUser loginUser = getLoginUser();
        SysUser sysUser = loginUser.getUser();
        sysUser.setPlatformGpsId(id);
        if (userService.updateUser(sysUser)>0){
            tokenService.setLoginUser(loginUser);
            return AjaxResult.success();
        }
        return error("添加失败，请查询当前用户是否存在");
    }



    /**
     * 获取所有用户列表
     */
    @GetMapping("/getList")
    @Anonymous
    public TableDataInfo getList(SysUser user) {
        List<SysUser> list = userService.selectUserListByParam(user);
        return getDataTable(list);
    }


    @Log(title = "用户管理", businessType = BusinessType.EXPORT)
    @PreAuthorize("@ss.hasPermi('system:user:export')")
    @PostMapping("/export")
    public void export(HttpServletResponse response, SysUser user) {
        List<SysUser> list = userService.selectUserList(user);
        ExcelUtil<SysUser> util = new ExcelUtil<SysUser>(SysUser.class);
        util.exportExcel(response, list, "用户数据");
    }

    @Log(title = "用户管理", businessType = BusinessType.IMPORT)
    @PreAuthorize("@ss.hasPermi('system:user:import')")
    @PostMapping("/importData")
    public AjaxResult importData(MultipartFile file, boolean updateSupport) throws Exception {
        ExcelUtil<SysUser> util = new ExcelUtil<SysUser>(SysUser.class);
        List<SysUser> userList = util.importExcel(file.getInputStream());
        String operName = getUsername();
        String message = userService.importUser(userList, updateSupport, operName);
        return success(message);
    }

    @PostMapping("/importTemplate")
    public void importTemplate(HttpServletResponse response) {
        ExcelUtil<SysUser> util = new ExcelUtil<SysUser>(SysUser.class);
        util.importTemplateExcel(response, "用户数据");
    }

    /**
     * 根据用户编号获取详细信息
     */
    @PreAuthorize("@ss.hasPermi('system:user:query')")
    @GetMapping(value = {"/", "/{userId}"})
    public AjaxResult getInfo(@PathVariable(value = "userId", required = false) Long userId) {
        userService.checkUserDataScope(userId);
        AjaxResult ajax = AjaxResult.success();
        List<SysRole> roles = roleService.selectAllRoleList(new SysRole());
        ajax.put("roles", SysUser.isAdmin(userId) ? roles : roles.stream().filter(r -> !r.isAdmin()).collect(Collectors.toList()));
        ajax.put("posts", postService.selectPostAll());
        if (StringUtils.isNotNull(userId)) {
            SysUser sysUser = userService.selectUserById(userId);
            ajax.put(AjaxResult.DATA_TAG, sysUser);
            ajax.put("postIds", postService.selectPostListByUserId(userId));
            ajax.put("roleIds", sysUser.getRoles().stream().map(SysRole::getRoleId).collect(Collectors.toList()));
//            ajax.put("roleIds", sysUser.getRoles().get(0).getRoleId());
            ajax.put("shopIds", sysUser.getShopIds());
        }
        return ajax;
    }

    /**
     * 根据用户编号获取gps信息
     */
    @GetMapping(value = {"/getGPSInfoByUserId/{userId}"})
    public AjaxResult getGPSInfoByUserId(@PathVariable(value = "userId", required = false) Long userId) {
        if (StringUtils.isNotNull(userId)) {
        List<Long> roleIds = new ArrayList();
        SysUser user = SecurityUtils.getLoginUser().getUser();
        List<SysRole> roles = user.getRoles();
        if (roles != null && !roles.isEmpty()) {
            for (SysRole role : roles) {
                if (role != null) {
                    roleIds.add(role.getRoleId());
                }
            }
        }
        if (roleIds != null && roleIds.size() > 0) {
            for (Long roleId : roleIds) {
                if (roleId >= 4) {
                    Long deptId = user.getDeptId();
                    if (deptId != null) {
                        SysDept sysDept = deptService.selectDeptById(deptId);
                        if (sysDept != null) {
                            SysUser users = new SysUser();
                            users.setDeptId(sysDept.getParentId());
                            List<SysUser> sysUsers = userService.selectUserListByParam(users);
                            if (sysUsers != null && sysUsers.size() > 0) {
                                for (SysUser sysUser : sysUsers) {
                                    SysUser obj = userService.selectUserById(userId);
                                    obj.setGpsUserName(sysUser.getGpsUserName());
                                    obj.setGpsPassword(sysUser.getGpsPassword());
                                    return AjaxResult.success(obj);
                                }
                            }
                        }
                    }
                }
            }
        }
            return AjaxResult.success(userService.selectUserById(userId));
        }
        return AjaxResult.success(new SysUser());
    }

    /**
     * 根据用户ID获取详细信息
     */
    @GetMapping("/getUserInfo/{userId}")
    @Anonymous
    public AjaxResult getUserInfoById(@PathVariable(value = "userId", required = true) Long userId) {
        AjaxResult ajax = AjaxResult.success();
        SysUser sysUser = userService.selectUserById(userId);
        ajax.put(AjaxResult.DATA_TAG, sysUser);
        return ajax;
    }

    /**
     * 新增用户
     */
    @PreAuthorize("@ss.hasPermi('system:user:add')")
    @Log(title = "用户管理", businessType = BusinessType.INSERT)
    @PostMapping
    public AjaxResult add(@Validated @RequestBody SysUser user) {
        if (!userService.checkUserNameUnique(user)) {
            return error("新增用户'" + user.getUserName() + "'失败，登录账号已存在");
        } else if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(user)) {
            return error("新增用户'" + user.getUserName() + "'失败，手机号码已存在");
        } else if (StringUtils.isNotEmpty(user.getEmail()) && !userService.checkEmailUnique(user)) {
            return error("新增用户'" + user.getUserName() + "'失败，邮箱账号已存在");
        }
        user.setCreateBy(getUsername());
        user.setPassword(SecurityUtils.encryptPassword(user.getPassword()));
        user.setEncryptedPass(MD5Util.getMD5(user.getPassword()));
        return toAjax(userService.insertUser(user));
    }

    /**
     * 修改用户
     */
    @PreAuthorize("@ss.hasPermi('system:user:edit')")
    @Log(title = "用户管理", businessType = BusinessType.UPDATE)
    @PutMapping
    @Anonymous
    public AjaxResult edit(@Validated @RequestBody SysUser user) {
        userService.checkUserAllowed(user);

        // TODO: 需要另外写接口，当前接口只能临时实现功能，注释掉组织架构筛选，该功能是操作只允许操作当前组织架构人员的数据
        //userService.checkUserDataScope(user.getUserId());

        if (!userService.checkUserNameUnique(user)) {
            return error("修改用户'" + user.getUserName() + "'失败，登录账号已存在");
        } else if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(user)) {
            return error("修改用户'" + user.getUserName() + "'失败，手机号码已存在");
        } else if (StringUtils.isNotEmpty(user.getEmail()) && !userService.checkEmailUnique(user)) {
            return error("修改用户'" + user.getUserName() + "'失败，邮箱账号已存在");
        }

        user.setUpdateBy(getUsername());
        return toAjax(userService.updateUser(user));
    }

    /**
     * 修改GPS用户
     */
    @PreAuthorize("@ss.hasPermi('system:user:edit')")
    @Log(title = "用户管理", businessType = BusinessType.UPDATE)
    @PutMapping("/editGPSInfo")
    @Anonymous
    public AjaxResult editGPSInfo(@Validated @RequestBody SysUser user) throws Exception {
        userService.checkUserAllowed(user);
        userService.checkUserDataScope(user.getUserId());
        try {
            JSONObject gpsTokenByUser = RestTemplateUtil.getGpsTokenByUser(RuoYiConfig.getGpsUrl(), user.getGpsUserName(), user.getGpsPassword());
            if (gpsTokenByUser == null) {
                return AjaxResult.error("用户名或者密码错误!");
            }
        } catch (Exception ex) {
            ex.printStackTrace();

        }
        user.setUpdateBy(getUsername());
        return toAjax(userService.updateUserInfo(user));
    }

    /**
     * 修改用户角色
     */
    @Log(title = "修改用户角色", businessType = BusinessType.UPDATE)
    @PutMapping("/updateRole")
    @Anonymous
    public AjaxResult updateRole(@Validated @RequestBody SysUser user) {
        userService.checkUserAllowed(user);
        return toAjax(userService.updateRole(user));
    }

    /**
     * 修改用户部门
     */
    @Log(title = "修改用户角色", businessType = BusinessType.UPDATE)
    @PutMapping("/updateDept")
    @Anonymous
    public AjaxResult updateDept(@Validated @RequestBody SysUser user) {
        userService.checkUserAllowed(user);
        return toAjax(userService.updateUserInfo(user));
    }

    /**
     * 修改用户部门以及角色
     */
    @Log(title = "修改用户角色", businessType = BusinessType.UPDATE)
    @PutMapping("/updateDeptRole")
    @Anonymous
    public AjaxResult updateDeptRole(@Validated @RequestBody SysUser user) {
        userService.checkUserAllowed(user);
        userService.updateRole(user);
        return toAjax(userService.updateUserInfo(user));
    }

    /**
     * 修改用户信息
     */
    @Log(title = "用户管理", businessType = BusinessType.UPDATE)
    @PutMapping("/updateInfo")
    @Anonymous
    public AjaxResult updateInfo(@Validated @RequestBody SysUser user) {
        if (user != null) {
            String code = user.getCode();
            String phonenumber = user.getPhonenumber();
            if (code == null&&StringUtils.isNotBlank(code)) {
                user.setPhonenumber(null);
            } else {
                if (StringUtils.isNoneBlank(phonenumber)) {
                    String smsCode=sharedData.get(phonenumber)==null?null:sharedData.get(phonenumber).toString();
                    if (StringUtils.isNotBlank(smsCode)) {
                        if (!smsCode.equals(code)) {
                            return error("手机验证码输入不正确！");
                        }
                    }else{
                        return error("验证码错误");
                    }
                } else {
                    return error("手机号不能为空！");
                }
            }
        }
        userService.checkUserAllowed(user);
        if (!userService.checkUserNameUnique(user)) {
            return error("修改用户'" + user.getUserName() + "'失败，登录账号已存在");
        } else if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(user)) {
            return error("修改用户'" + user.getUserName() + "'失败，手机号码已存在");
        } else if (StringUtils.isNotEmpty(user.getEmail()) && !userService.checkEmailUnique(user)) {
            return error("修改用户'" + user.getUserName() + "'失败，邮箱账号已存在");
        }
        return toAjax(userService.updateUserInfo(user));
    }

    /**
     * 删除用户
     */
    @PreAuthorize("@ss.hasPermi('system:user:remove')")
    @Log(title = "用户管理", businessType = BusinessType.DELETE)
    @DeleteMapping("/{userIds}")
    public AjaxResult remove(@PathVariable Long[] userIds) {
        if (ArrayUtils.contains(userIds, getUserId())) {
            return error("当前用户不能删除");
        }
        return toAjax(userService.deleteUserByIds(userIds));
    }

    /**
     * 重置密码
     */
    @PreAuthorize("@ss.hasPermi('system:user:resetPwd')")
    @Log(title = "用户管理", businessType = BusinessType.UPDATE)
    @PutMapping("/resetPwd")
    public AjaxResult resetPwd(@RequestBody SysUser user) {
        userService.checkUserAllowed(user);
        userService.checkUserDataScope(user.getUserId());
        user.setPassword(SecurityUtils.encryptPassword(user.getPassword()));
        user.setUpdateBy(getUsername());
        return toAjax(userService.resetPwd(user));
    }

    /**
     * 状态修改
     */
    @PreAuthorize("@ss.hasPermi('system:user:edit')")
    @Log(title = "用户管理", businessType = BusinessType.UPDATE)
    @PutMapping("/changeStatus")
    public AjaxResult changeStatus(@RequestBody SysUser user) {
        userService.checkUserAllowed(user);
        userService.checkUserDataScope(user.getUserId());
        user.setUpdateBy(getUsername());
        return toAjax(userService.updateUserStatus(user));
    }

    /**
     * 根据用户编号获取授权角色
     */
    @PreAuthorize("@ss.hasPermi('system:user:query')")
    @GetMapping("/authRole/{userId}")
    public AjaxResult authRole(@PathVariable("userId") Long userId) {
        AjaxResult ajax = AjaxResult.success();
        SysUser user = userService.selectUserById(userId);
        List<SysRole> roles = roleService.selectRolesByUserId(userId);
        ajax.put("user", user);
        ajax.put("roles", SysUser.isAdmin(userId) ? roles : roles.stream().filter(r -> !r.isAdmin()).collect(Collectors.toList()));
        return ajax;
    }

    /**
     * 用户授权角色
     */
    @PreAuthorize("@ss.hasPermi('system:user:edit')")
    @Log(title = "用户管理", businessType = BusinessType.GRANT)
    @PutMapping("/authRole")
    public AjaxResult insertAuthRole(Long userId, Long[] roleIds) {
        userService.checkUserDataScope(userId);
        userService.insertUserAuth(userId, roleIds);
        return success();
    }

    /**
     * 获取部门树列表
     */
    @PreAuthorize("@ss.hasPermi('system:user:list')")
    @GetMapping("/deptTree")
    public AjaxResult deptTree(SysDept dept) {
        return success(deptService.selectDeptTreeList(dept));
    }

    /**
     * 企业工商营业执照图片上传
     */
    @Log(title = "企业工商营业执照图片", businessType = BusinessType.UPDATE)
    @PostMapping("/upload/files")
    @Anonymous
    public AjaxResult uploadFiles(List<MultipartFile> files) throws Exception {
        List<String> urls = new ArrayList<String>();
        if (!files.isEmpty()) {
            for (MultipartFile file : files) {
                String cominfourl = FileUploadUtils.upload(RuoYiConfig.getBussPicsPath(), file, MimeTypeUtils.IMAGE_EXTENSION);
                urls.add("/prod-api" + cominfourl);
            }
            AjaxResult ajax = AjaxResult.success();
            ajax.put("urls", StringUtils.join(urls, FILE_DELIMETER));
            return ajax;

        }

        return error("上传图片异常，请联系管理员");
    }

    /**
     * 用户身份证图片上传
     */
    @Log(title = "用户身份证图片", businessType = BusinessType.UPDATE)
    @PostMapping("/upload/certifiles")
    @Anonymous
    public AjaxResult uploadCertiFiles(List<MultipartFile> files) throws Exception {
        List<String> urls = new ArrayList<String>();
        if (!files.isEmpty()) {
            for (MultipartFile file : files) {
                String idcardurl = FileUploadUtils.upload(RuoYiConfig.getIdCardPicsPath(), file, MimeTypeUtils.IMAGE_EXTENSION);
                urls.add("/prod-api" + idcardurl);
            }
            AjaxResult ajax = AjaxResult.success();
            ajax.put("urls", StringUtils.join(urls, FILE_DELIMETER));
            return ajax;

        }

        return error("上传图片异常，请联系管理员");
    }

    /**
     * 人脸识别图片上传接口
     */
    @Log(title = "人脸识别图片", businessType = BusinessType.UPDATE)
    @PostMapping("/upload/facialfiles")
    @Anonymous
    public AjaxResult uploadFacialFiles(MultipartFile file) throws Exception {
        if (!file.isEmpty()) {
            String facialpicurl = FileUploadUtils.upload(RuoYiConfig.getFacialRecoPath(), file, MimeTypeUtils.IMAGE_EXTENSION);
            AjaxResult ajax = AjaxResult.success();
            ajax.put("url", "/prod-api" + facialpicurl);
            return ajax;
        }

        return error("上传图片异常，请联系管理员");
    }

    @GetMapping("/notBranchAdmin")
    public TableDataInfo selectNotBranchAdmin(@RequestParam Long bid) {
        startPage();
        return getDataTable(userService.selectNotBranchAdmin(bid));
    }
}
